/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Stats.h"
#include "myassert.h"
#include "Utils.h"
#include "StringBuilder.h"

using namespace Chronos;
using namespace std;

static const char* DELIMITER = ",";

Stats::Stats(const string& init) : health(0) {
    memset(base, unknown, sizeof(base));
    memset(total, unknown, sizeof(total));
    if (init != "") {
        char buf[init.length()+1];
        strcpy(buf, init.c_str());
        char* number = strtok(buf, DELIMITER); 
        ASSERT_NOT_NULL(number);
        for (int i=0; i<Stats::MAX; ++i) {
            set((Stat)i, atoi(number));
            number = strtok(0, DELIMITER); 
            ASSERT_NOT_NULL(number);
        }
        health = atoi(number);
    }
}


Stats::Stats(const Stats& rhs) {
    memcpy(base, rhs.base, sizeof(base));
    memcpy(total, rhs.total, sizeof(total));
    health = rhs.health;
}


void Stats::set(Stat stat, int value) {
    base[stat] = value;
    total[stat] = value;

    if (stat == maxHealth) { health = value; }
}


void Stats::modify(Stat stat, int modifier) {
    total[stat] += modifier;

    if (stat == maxHealth) normalizeHealth();
}


void Stats::unmodify(Stat stat, int modifier) {
    total[stat] -= modifier;

    if (stat == maxHealth) normalizeHealth();
}


int Stats::operator[] (Stat i) const {
    ASSERT_TRUE(i < MAX);
    return total[i];
}


int Stats::getBase(Stat i) const {
    ASSERT_TRUE(i < MAX);
    return base[i];
}


int Stats::getHealth() const { return health; }

void Stats::setHealth(int value) {
    health = value;
    normalizeHealth();
}

void Stats::modifyHealth(int amount) {
    health += amount;
    normalizeHealth();
}


void Stats::serialize(StringBuilder& buffer) const {
    for (int i=0; i<Stats::MAX; ++i) {
        buffer << base[i] << DELIMITER;
    }
    buffer << health;
}


void Stats::normalizeHealth() {
    if (health > total[maxHealth]) health = total[maxHealth];
}

const char* const Stats::toStr[] = {
      "max health"
    , "speed"
    , "max damage"
    , "hit chance"
};

